package bp.wf.minio;

import bp.da.DataType;
import bp.da.Log;
import bp.difference.SystemConfig;
import io.minio.*;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;

public class MinioUtil {
    private static MinioUtil instance;
    private MinioClient minioClient;
    private String minioHost;
    private String minioAccessKey;
    private String minioSecretKey;
    private String minioBucket;

    private MinioUtil() {
        try {
            // 检查配置
            checkConfigs();
            // 实例化minio客户端
            minioClient = MinioClient.builder().endpoint(getMinioHost()) // Minio 服务器地址
                    .credentials(getMinioAccessKey(), getMinioSecretKey()) // 访问密钥和秘密密钥
                    .build();
            createBucketIfNotExists(getMinioBucket());
            Log.DebugWriteInfo("√ minio客户端实例化成功.");
        } catch (Exception e) {
            Log.DebugWriteError(e);
        }
    }

    public static MinioUtil getInstance() {
        if (instance == null) {
            synchronized (MinioUtil.class) {
                if (instance == null) {
                    instance = new MinioUtil();
                }
            }
        }
        return instance;
    }

    public String getMinioHost() {
        return minioHost;
    }

    public void setMinioHost(String minioHost) {
        this.minioHost = minioHost;
    }

    public String getMinioAccessKey() {
        return minioAccessKey;
    }

    public void setMinioAccessKey(String minioAccessKey) {
        this.minioAccessKey = minioAccessKey;
    }

    public String getMinioSecretKey() {
        return minioSecretKey;
    }

    public void setMinioSecretKey(String minioSecretKey) {
        this.minioSecretKey = minioSecretKey;
    }

    public String getMinioBucket() {
        return minioBucket;
    }

    public void setMinioBucket(String minioBucket) {
        this.minioBucket = minioBucket;
    }

    private void checkConfigs() {
        String minioHost = SystemConfig.getMinioHost();
        if (DataType.IsNullOrEmpty(minioHost)) {
            throw new RuntimeException("Minio host 未设置，请您在jflow.properties中配置");
        }
        setMinioHost(minioHost);
        String minioAccessKey = SystemConfig.getMinioAccessKey();
        if (DataType.IsNullOrEmpty(minioAccessKey)) {
            throw new RuntimeException("Minio access key 未设置，请您在jflow.properties中配置");
        }
        setMinioAccessKey(minioAccessKey);
        String minioSecretKey = SystemConfig.getMinioSecretKey();
        if (DataType.IsNullOrEmpty(minioSecretKey)) {
            throw new RuntimeException("Minio secret key 未设置，请您在jflow.properties中配置");
        }
        setMinioSecretKey(minioSecretKey);
        String minioBucket = SystemConfig.getMinioBucket();
        if (DataType.IsNullOrEmpty(minioBucket)) {
            throw new RuntimeException("Minio bucket 未设置，请您在jflow.properties中配置");
        }
        setMinioBucket(minioBucket);
    }

    public void createBucketIfNotExists(String bucketName) {
        try {
            boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
            if (!found) {
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
                Log.DebugWriteInfo("Bucket [" + bucketName + "] 创建成功.");
            } else {
                Log.DebugWriteInfo("√ Bucket [" + bucketName + "] 已存在.");
            }
        } catch (Exception e) {
            Log.DebugWriteError(e);
        }
    }

    public void uploadObject(String objectName, byte[] data, String contentType) {
        try (InputStream inputStream = new ByteArrayInputStream(data)) {
            minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(getMinioBucket())
                            .object(objectName)
                            .contentType(contentType)
                            .stream(inputStream, data.length, -1)
                            .build()
            );
            Log.DebugWriteInfo("√ 对象上传成功.");
        } catch (Exception e) {
            Log.DebugWriteError(e);
        }
    }

    public void downloadObject(String objectName, String tempFile) {
        try (InputStream is = minioClient.getObject(
                GetObjectArgs.builder()
                        .bucket(getMinioBucket())
                        .object(objectName)
                        .build());
             OutputStream outStream = Files.newOutputStream(Paths.get(tempFile))) {
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = is.read(buffer)) != -1) {
                outStream.write(buffer, 0, bytesRead);
            }
            Log.DebugWriteInfo("√ 对象下载成功.");
        } catch (Exception e) {
            Log.DebugWriteError(e);
        }
    }

    public void deleteObject(String objectName) {
        try {
            minioClient.removeObject(
                    RemoveObjectArgs.builder()
                            .bucket(getMinioBucket())
                            .object(objectName)
                            .build());
            Log.DebugWriteInfo("√ 对象删除成功.");
        } catch (Exception e) {
            Log.DebugWriteError(e);
        }
    }

    public String getAccessPath(String objectName) {
        return getMinioHost() + "/" + getMinioBucket() + "/" + objectName;
    }
}
